package cn.mw.cmdb.processor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.mw.cmdb.entity.CustomClassificationPropertyInfo;
import cn.mw.cmdb.entity.CustomClassificationVo;
import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.enums.TableViewTypeEnum;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.TableSearchParam;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomClassificationServiceImpl;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.util.AssetsTool;
import cn.mw.cmdb.view.TreeViewObject;
import cn.mw.microMonitorCommon.api.cmdb.TableIdEnum;
import cn.mw.microMonitorCommon.api.cmdb.TreeView;
import cn.mw.microMonitorCommon.api.cmdb.TreeViewType;
import cn.mw.microMonitorCommon.api.common.Constants;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TreeProcessorCustom implements TreeProccessorTable {
    private CmdbServiceManage cmdbServiceManage;

    private TableSearchParam tableSearchParam;

    public TreeProcessorCustom(CmdbServiceManage cmdbServiceManage, TableSearchParam tableSearchParam) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableSearchParam = tableSearchParam;
    }

    @Override
    public List genTreeData(TableDataProcessorContext context) throws Exception {
        List<TreeView> list = new ArrayList();
        CustomClassificationServiceImpl customClassificationService = (CustomClassificationServiceImpl) cmdbServiceManage.getModelService(CustomClassificationServiceImpl.ID);
        CustomClassificationVo customClassificationVo=customClassificationService.doSelectById(tableSearchParam.getTableId());
        if (customClassificationVo==null){
            return list;
        }

        // 按照分类属性进行分组
        List<CustomClassificationPropertyInfo> customClassificationPropertyInfoList = customClassificationVo.getPropertyInfoList();
        customClassificationPropertyInfoList.sort(Comparator.comparingInt(CustomClassificationPropertyInfo::getLevel));
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        List<ModelInfo> modelInfos = customModelService.selectByTreeViewList(customClassificationVo.getTreeViewList());
        if (null != modelInfos) {
            List<String> modelIds=modelInfos.stream().map(ModelInfo::getId).toList();
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
            instanceSearchParam.setModelIds(modelIds);
            BeanUtil.copyProperties(context.getTableSearchParam(), instanceSearchParam, CopyOptions.create().setIgnoreNullValue(true));
            List<InstanceInfoExtend> instanceInfoList = instanceService.aggregateList(instanceSearchParam);
            if (!CollectionUtils.isEmpty(instanceInfoList)) {
                if (!CollectionUtils.isEmpty(customClassificationPropertyInfoList)){
                    // 按照模型属性逐层分组
                    calcClassification(customClassificationPropertyInfoList,0,instanceInfoList,list,null);
                }
            }
        }
        return list;
    }

    private void calcClassification(List<CustomClassificationPropertyInfo> customClassificationPropertyInfoList, int currentLevel, List<InstanceInfoExtend> instanceInfoList, List<TreeView> treeViewList, Object parentId) {
        CustomClassificationPropertyInfo customClassificationPropertyInfo = customClassificationPropertyInfoList.get(currentLevel);
        Map<String, List<InstanceInfoExtend>> field2InstanceListMap = instanceInfoList.stream().collect(Collectors.groupingBy(item ->
                item.getData().get(customClassificationPropertyInfo.getField()) == null ? Constants.UNKNOWN
                        : item.getData().get(customClassificationPropertyInfo.getField()).toString()));
        for (Map.Entry<String, List<InstanceInfoExtend>> entry : field2InstanceListMap.entrySet()) {
            TreeViewObject treeViewObject = new TreeViewObject();
            if (parentId == null) {
                treeViewObject.setId(customClassificationPropertyInfo.getField() + Constants.PROPERTY_SPLIT + entry.getKey());
            } else {
                treeViewObject.setId(parentId + Constants.ID_SPLIT + customClassificationPropertyInfo.getField() + Constants.PROPERTY_SPLIT + entry.getKey());
            }
            treeViewObject.setItemName(entry.getKey());
            treeViewObject.setParentId(parentId);
            treeViewObject.setCount(entry.getValue().size());
            treeViewObject.setType(TreeViewType.custom.name());
            treeViewObject.setHeaderType(TableIdEnum.instance.getCode());
            treeViewObject.setViewType(TableViewTypeEnum.list.getCode());
            treeViewObject.setItemAssetsStatus(AssetsTool.calcItemAssetsStatus(entry.getValue(), treeViewObject));
            treeViewList.add(treeViewObject);
            if (currentLevel < customClassificationPropertyInfoList.size() - 1) {
                calcClassification(customClassificationPropertyInfoList, currentLevel + 1, entry.getValue(), treeViewList, treeViewObject.getId());
            }
        }
    }
}
